/* Copyright (c) 2010, David Kreuter. See LICENSE for more information */

#include "headers.h"

bmd *read_bmd(uint8 *buf, uint32 len){
	START(read_bmd);
	bmd *b=(bmd*)malloc(sizeof(bmd));
	b->len=len;
	b->m=(mdl*)0;
	b->t=(tex*)0;

	MAGIC(0,BMD0,read_bmd);
	CHECK_LEN(8,read_bmd);
	uint16 i, num_blocks=RS(14);
	DEBUG("%d blocks\n",num_blocks);
	uint32 *offset=(uint32*)(buf+16);
	for(i=0;i<num_blocks;i++){
		DEBUG("block #%d      Pos:%8x Len:%8x End:%8x\n",
			i,offset[i],RL(offset[i]+4),offset[i]+RL(offset[i]+4));
		ident++;
		switch(RL(offset[i])){
		case MDL0:
			DEBUG("=MDL0\n");
			if(!(b->m=read_mdl(buf+offset[i],RL(offset[i]+4)))){
				ERROR("while reading a MDL0\n");
				ident--;goto read_bmd_error;
			}
			break;
		case TEX0:
			DEBUG("=TEX0\n");
			if(!(b->t=read_tex(buf+offset[i],RL(offset[i]+4)))){
				ERROR("while reading a TEX0\n");
				ident--;goto read_bmd_error;
			}
			break;
		default:
			DEBUG("= ???\n");
			break;
		}
		ident--;
	}
	END(read_bmd,b);
	free_bmd(b);
	return 0;
}

int write_bmd(bmd *b, uint8 *buf, uint32 len){
	START(write_bmd);
	uint16 num_blocks=((b->m)!=0)+((b->t)!=0);
	uint32 temp;
	RL(0)=BMD0;
	RL(4)=0x0002FEFF;
	RL(8)=len;
	RS(12)=16;
	RS(14)=num_blocks;
	uint16 i;temp=16+num_blocks*4;
	DEBUG("%d blocks\n",num_blocks);
	ident++;
	uint32 *sizes=(uint32*)calloc(4,num_blocks);
	for(i=0;i<num_blocks;i++){  // BAD HACK!
		RL(16+i*4)=temp;
		sizes[i]=(b->m&&!i)?size_mdl(b->m):size_tex(b->t);
		temp+=sizes[i];
	}
	for(i=0;i<num_blocks;i++){
		temp=RL(16+i*4);
		DEBUG("block #%d      Pos:%8x Len:%8x End:%8x\n",
			i,RL(16+i*4),sizes[i],RL(16+i*4)+sizes[i]);
		if(!((b->m&&!i)?
			write_mdl(b->m,buf+temp,sizes[i]):
			write_tex(b->t,buf+temp,sizes[i])))
		{
			ERROR("while writing BMD\n");
			ident--;
			free(sizes);
			return 0;
		};
	}
	ident--;
	free(sizes);
	END(write_bmd,1);
}

void free_bmd(bmd *b){
	START(free_bmd);
	if(b){
		if(b->m)free_mdl(b->m);
		if(b->t)free_tex(b->t);
		free(b);
	}
	ENDV(free_bmd);
}

uint32 size_bmd(bmd *b){
	START(size_bmd);
	uint8 m=(b->m)!=0;
	uint8 t=(b->t )!=0;
	uint32 s=16+(m+t)*4;
	if(m)s+=size_mdl(b->m);
	if(t)s+=size_tex(b->t);
	if(s!=b->len){
		DEBUG("WTF! Real: %8x Calculated: %8x\n",s,b->len);
	}
	END(size_bmd,s);
}
